// Copyright (c) 2020-present, INSPUR Co, Ltd. All rights reserved.
// This source code is licensed under Apache 2.0 License.

#pragma once

#include "pure_mem/version_node.h"
#include <atomic>
#include <list>

namespace rocksdb {
// TreeVoidRef object pointer is stored as tree leaf node.
// tree just index user key, no HLC or sequence number.
// TreeVoidRef object contains multi version values for one user key.
class TreeVoidRef {
public:
  TreeVoidRef() {
    version_head_.store(nullptr);
    next_.store(nullptr);
    prev_.store(nullptr);
  }
  ~TreeVoidRef() {
    VersionNode *cur = version_head_.load(), *next = nullptr;
    while (cur != nullptr) {
      next = cur->Next();
      delete cur;
      cur = next;
    }
  }

  TreeVoidRef *Next() { return next_.load(); }
  TreeVoidRef *Prev() { return prev_.load(); }

  VersionNode *getContentList() { return this->version_head_.load(); }

  bool CASContentList(VersionNode *expected, VersionNode *x) {
    return version_head_.compare_exchange_strong(expected, x);
  }
  void setContentList(VersionNode *x) { return version_head_.store(x); }

  void setNext(TreeVoidRef *x) { return next_.store(x); }

  void setPrev(TreeVoidRef *x) { return prev_.store(x); }

  bool CASNext(TreeVoidRef *expected, TreeVoidRef *x) {
    return next_.compare_exchange_strong(expected, x);
  }

  bool CASPrev(TreeVoidRef *expected, TreeVoidRef *x) {
    return prev_.compare_exchange_strong(expected, x);
  }
  static int CompareTo(TreeVoidRef *other) {
    // cannot use this function.
    assert(false);
    return 0;
  }

private:
  // double link list, store multi version values of current key.
  std::atomic<VersionNode *> version_head_;
  // double link list of TreeVoidRef, each TreeVoidRef node need store prev and
  // next pointer.
  std::atomic<TreeVoidRef *> prev_;
  std::atomic<TreeVoidRef *> next_;
};
} // namespace rocksdb